using Admin.NET.Application.Entity;
using Admin.NET.Core;
using Furion.DependencyInjection;
using Microsoft.AspNetCore.Authorization;
using SqlSugar;

namespace Admin.NET.Application.Service.Report;

/// <summary>
/// 入库流水报表服务（仅入库）
/// </summary>
[ApiDescriptionSettings("Report", Name = "inFlow", Order = 899)]
[Route("api/report/inFlow")]
[AllowAnonymous]
public class InFlowReportService : IDynamicApiController, ITransient
{
	private readonly ISqlSugarClient _sqlSugarClient;

	public InFlowReportService(ISqlSugarClient sqlSugarClient)
	{
		_sqlSugarClient = sqlSugarClient;
	}

	/// <summary>
	/// 入库流水分页查询（按时间范围、供应商/物品类别、仓库、经办人、制单人/制单时间等筛选）
	/// </summary>
	[HttpPost("page")]
	public async Task<object> Page([FromBody] GetInFlowInput input)
	{
		DateTime? inStart = input.StartTime?.Date;
		DateTime? inEnd = input.EndTime?.Date;
		if (inEnd != null)
		{
			inEnd = inEnd.Value.AddDays(1).AddTicks(-1);
		}

		// 这里入库采用 Sysinstockorder 聚合信息；若有更详细供应商/类别，可由 GoodsModel/购买单联查
		var query = _sqlSugarClient.Queryable<Sysinstockorder>()
			.WhereIF(inStart != null, o => o.InDate >= inStart)
			.WhereIF(inEnd != null, o => o.InDate <= inEnd)
			.WhereIF(!string.IsNullOrWhiteSpace(input.WarehouseName), o => o.WarehouseName!.Contains(input.WarehouseName!))
			.WhereIF(!string.IsNullOrWhiteSpace(input.GoodsOrCategory), o => o.GoodsName!.Contains(input.GoodsOrCategory!))
			.WhereIF(!string.IsNullOrWhiteSpace(input.OperatorName), o => o.AgentName!.Contains(input.OperatorName!))
			// 供应商信息位于采购单表，尝试通过来源单号/货品名称匹配（若存在）。没有则忽略筛选。
			.LeftJoin<Syspurchaseorder>((o, p) => o.RelatedCode == p.Code)
			.WhereIF(!string.IsNullOrWhiteSpace(input.SupplierName), (o, p) => p.Supplier!.Contains(input.SupplierName!))
			.LeftJoin<SysOrg>((o, p, org) => o.OrgId == org.Id)
			.Select((o, p, org) => new InFlowRowOutput
			{
				BillNo = o.Code,
				BizTime = o.InDate,
				InType = o.InType,
				SupplierName = p.Supplier,
				GoodsName = o.GoodsName,
				WarehouseName = o.WarehouseName,
				Quantity = o.InQuantity,
				Amount = o.WarehouseAmount,
				UnitPrice = SqlFunc.IIF(o.InQuantity == 0, 0, o.WarehouseAmount / (decimal)o.InQuantity),
				OperatorName = o.AgentName,
				MakerName = o.CreateUserName,
				DeptName = org.Name,
				MakeTime = o.CreateTime,
				AuditorName = o.UpdateUserName,
				AuditTime = o.UpdateTime,
				Remark = o.Remark
			});

		var total = new RefAsync<int>();
		var list = await query.ToPageListAsync(input.Page, input.PageSize, total);

		return new
		{
			Items = list,
			Total = total.Value,
			Page = input.Page,
			PageSize = input.PageSize
		};
	}

	/// <summary>
	/// 入库流水统计（单据数、入库数量、入库金额）
	/// </summary>
	[HttpPost("stats")]
	public async Task<InFlowStatsOutput> Stats([FromBody] GetInFlowInput input)
	{
		DateTime? inStart = input.StartTime?.Date;
		DateTime? inEnd = input.EndTime?.Date;
		if (inEnd != null)
		{
			inEnd = inEnd.Value.AddDays(1).AddTicks(-1);
		}

		var query = _sqlSugarClient.Queryable<Sysinstockorder>()
			.WhereIF(inStart != null, o => o.InDate >= inStart)
			.WhereIF(inEnd != null, o => o.InDate <= inEnd)
			.WhereIF(!string.IsNullOrWhiteSpace(input.WarehouseName), o => o.WarehouseName!.Contains(input.WarehouseName!))
			.WhereIF(!string.IsNullOrWhiteSpace(input.GoodsOrCategory), o => o.GoodsName!.Contains(input.GoodsOrCategory!))
			.WhereIF(!string.IsNullOrWhiteSpace(input.OperatorName), o => o.AgentName!.Contains(input.OperatorName!))
			.LeftJoin<Syspurchaseorder>((o, p) => o.RelatedCode == p.Code)
			.WhereIF(!string.IsNullOrWhiteSpace(input.SupplierName), (o, p) => p.Supplier!.Contains(input.SupplierName!));

		return new InFlowStatsOutput
		{
			BillCount = await query.CountAsync(),
			InQuantity = await query.SumAsync(o => o.InQuantity),
			InAmount = await query.SumAsync(o => o.WarehouseAmount)
		};
	}
}

public class GetInFlowInput
{
	public DateTime? StartTime { get; set; }
	public DateTime? EndTime { get; set; }
	public string? SupplierName { get; set; }
	public string? GoodsOrCategory { get; set; }
	public string? WarehouseName { get; set; }
	public string? OperatorName { get; set; }
	public int Page { get; set; } = 1;
	public int PageSize { get; set; } = 10;
}

public class InFlowRowOutput
{
	public string BillNo { get; set; } = string.Empty;
	public DateTime BizTime { get; set; }
	public string? InType { get; set; }
	public string? SupplierName { get; set; }
	public string? GoodsName { get; set; }
	public string? WarehouseName { get; set; }
	public int Quantity { get; set; }
	public decimal Amount { get; set; }
	public decimal UnitPrice { get; set; }
	public string? OperatorName { get; set; }
	public string? MakerName { get; set; }
	public string? DeptName { get; set; }
	public DateTime? MakeTime { get; set; }
	public string? AuditorName { get; set; }
	public DateTime? AuditTime { get; set; }
	public string? Remark { get; set; }
}

public class InFlowStatsOutput
{
	public int BillCount { get; set; }
	public int? InQuantity { get; set; }
	public decimal? InAmount { get; set; }
}


